#include <string>
#include <iostream>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include "../../include/strategy/webservice.h"
using json = nlohmann::json;
using namespace std;

void WebService::init()
{
    allUsers = new StrategyService[MAX_FD];
    InfoLog("start webservice init");
    string inConfigFile = "/home/renyu/桌面/binanceC++server/config.json";
    ifstream in(inConfigFile);
    json config = json::parse(in);
    in.close();
    port = config["port"];
    listenFd = socket(PF_INET, SOCK_STREAM, 0);
    assert(listenFd >= 0);

    int ret = 0;
    struct sockaddr_in address;
    bzero(&address, sizeof(address));
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = htonl(INADDR_ANY);
    address.sin_port = htons(port);

    ret = bind(listenFd, (struct sockaddr *)&address, sizeof(address));
    assert(ret >= 0);
    ret = listen(listenFd, 5);
    assert(ret >= 0);

    //epoll创建内核事件表
    epoll_event event;
    epollFd = epoll_create(5);
    assert(epollFd != -1);
    event.events = EPOLLIN | EPOLLRDHUP;
    event.data.fd = listenFd;
    epoll_ctl(epollFd, EPOLL_CTL_ADD, listenFd, &event);

    threadNumber = config["threadNums"];//需要封装一个函数读取配置
    InfoLog("start build threadpool, thread num is[%u]", threadNumber);
    threadPool = new ThreadPool(threadNumber);

    coinPrice = CoinPrice::getInstance();
}

void WebService::startListen()
{
    InfoLog("start listen");
    while (1)
    {
        InfoLog("start while");
        int listenNums = epoll_wait(epollFd, events, MAX_EVENT_NUMBER, -1);
        InfoLog("listenNums:[%u]", listenNums);
        if(listenNums == -1)
        {
            ErrorLog("epoll failure");
            break;
        }
        for(int i = 0; i < listenNums; ++i)
        {
            int clientFd = events[i].data.fd;
            if(clientFd == listenFd)
            {
                struct sockaddr_in client_address;
                socklen_t client_addrlength = sizeof(client_address);
                int connfd = accept(listenFd, (struct sockaddr *)&client_address, &client_addrlength);
                if (connfd < 0)
                {
                    ErrorLog("accept error");
                    break;
                }
                event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
                event.data.fd = connfd;
                epoll_ctl(epollFd, EPOLL_CTL_ADD, connfd, &event);
                allUsers[connfd].init(connfd, epollFd);
                InfoLog("connected client:[%u]", connfd);
            }
            else if(events[i].events & EPOLLIN)
            {
                assert(dealReadMessage(clientFd) == true);
            }
            else if(events[i].events & EPOLLOUT)
            {
                assert(dealWriteMessage(clientFd) == true);
            }
        }
    }
}

bool WebService::dealReadMessage(int clientFd)
{
    InfoLog("start read message");
    InfoLog("allusers read clientfd:[%u]", allUsers[clientFd].sockFd);
    threadPool->push(allUsers + clientFd, 0);
    return true;
}

bool WebService::dealWriteMessage(int clientFd)
{
    InfoLog("start write message");
    InfoLog("allusers write clientfd:[%u]", allUsers[clientFd].sockFd);
    threadPool->push(allUsers + clientFd, 1);
}